#pragma once

/*
// KCP server with id and (ip, port) address
*/

#include <string>
#include "kcp_typedef.h"
#include "type.h"
#include <functional>
#include "knet.h"
#include "asio/asio.hpp"

namespace KCP {
	class CConnection;
	class CConnectionMgr;

	class CKCPServer : public IKServer, asio::noncopyable {
	public:
		// listen denotes server or client mode.
		// listen == true is listening else conencting.
		explicit CKCPServer(asio::io_service& ioService,
			const std::string& ip, uint16 port,
			IKSessionFactory* f, bool listen
		);
		virtual ~CKCPServer();

	public:
		// connection size.
		virtual size_t GNAPI GetConnectionSize();

		// stop server.
		virtual void GNAPI Stop();

	public:
		void   update();

		// set call back.
		void   set_callback(const std::function<event_callback_t>& func);

		// deal event callback.
		int    event_callback(CConnection* conn, eEventType eventType, const char* msg, int len);

		// stop all
		void   stop();

		// send udp msg to (ip,port) address.
		void   sendMsg(const char* ip, uint16 port, const char* msg, int len);

		// get connection mgr.
		CConnectionMgr* getConnMgr();

	public:
		// on recv: connection, data, len
		bool   onRecv(CConnection* conn, const char* data, int len);

		// connection close.
		void   onClose(CConnection* conn);

		// connection establish
		void   onEstablish(CConnection* conn, const char* data, int len);

	private:
		CConnectionMgr   *m_connections{nullptr};
		IKSessionFactory *m_sessionFactory{nullptr};
	};
}